package com.example.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.ProductionRecord;
import com.example.entity.dto.ProductionQueryReq;
import com.example.entity.dto.StyleImportDTO;
import com.example.listener.IndexOrNameDataListener;
import com.example.mapper.ProductionRecordMapper;
import com.example.service.GetUserToken;
import com.example.service.ProductionRecordService;
import com.example.util.JsonUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
public class ProductionRecordServiceImpl extends ServiceImpl<ProductionRecordMapper, ProductionRecord> implements ProductionRecordService {

    // 日志对象（SLF4J）
    private static final Logger log = LoggerFactory.getLogger(ProductionRecordServiceImpl.class);

    private final ProductionRecordMapper productionRecordMapper;

    private final GetUserToken getUserToken;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Value("${degao.url.selSchedule}")
    private String selSchedule;

    @Value("${degao.reqParams.facCode}")
    private String facCode;

    @Value("${degao.reqParams.category}")
    private String category;

    @Value("${degao.reqParams.startOpNo}")
    private String startOpNo;

    @Value("${degao.path.scheduleFilePath}")
    private String scheduleFilePath;
    //产量报表数据导入
    @Override
    public void ProductionDetailImport() {
        // 将表格数据清空
        productionRecordMapper.truncateTable();
        log.info("开始导入数据");
        String token = getUserToken.getUserToken();
        //从Excel提取请求参数
        List<StyleImportDTO> styleImportDTOS = readExcelData(scheduleFilePath);
        // 去除非法数据
        List<StyleImportDTO> list = styleImportDTOS
                .stream()
                .distinct()
                .filter(styleImportDTO -> !ObjectUtils.nullSafeEquals(styleImportDTO.getMo(),"0"))
                .toList();
        for (StyleImportDTO styleImportDTO : list) {
            //延迟5s 串列执行 ,避免系统宕机
            importExcelToDatabase(token,styleImportDTO);
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void importExcelToDatabase(String token, StyleImportDTO styleImportDTO) {
        //发送请求,获取领航系统数据
        HttpHeaders requestHeader = new HttpHeaders();
        requestHeader.setContentType(MediaType.APPLICATION_JSON);
        List<String> cookies = new ArrayList<>();
        cookies.add(token);
        requestHeader.put(HttpHeaders.COOKIE, cookies);
        ProductionQueryReq queryReq = new ProductionQueryReq();
        queryReq.setMo(ObjectUtils.isEmpty(styleImportDTO.getMo())?styleImportDTO.getMoAlias():styleImportDTO.getMo());
        queryReq.setFacCode(facCode);
        queryReq.setCategory(category);
        queryReq.setStartOpNo(startOpNo);
        log.info("请求参数:[{}],请求链接为:[{}]",queryReq.toString(),selSchedule);
        HttpEntity<ProductionQueryReq> entity = new HttpEntity<>(queryReq, requestHeader);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(selSchedule, entity, String.class);
        String json = responseEntity.getBody();
        // JSON --> 实体类
        try {
            Map<String, Object> map = objectMapper.readValue(json, new TypeReference<>() {
            });
            List<ProductionRecord> list = JsonUtil.objToList(map.get("list"), ProductionRecord.class);
            int batchSize = 1000;
            for (int i = 0; i < list.size(); i += batchSize) {
                int endIndex = Math.min(i + batchSize, list.size());
                List<ProductionRecord> batchList = list.subList(i, endIndex);
                //moAlias赋值
                batchList.forEach(pr -> pr.setMoAlias(styleImportDTO.getMoAlias()));
                if (saveBatch(batchList)) {
                    log.info("成功插入[{}]条,总共需插入[{}]条数据",batchList.size(),list.size());
                }
            }
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 测试EasyExcel 读取功能
     */
    @Override
    public void demo() {
        List<StyleImportDTO> styleImportDTOS = readExcelData(scheduleFilePath);
//        styleImportDTOS.forEach(System.out::println);
    }

    @Override
    public boolean saveBatch(Collection<ProductionRecord> entityList) {
        return super.saveBatch(entityList);
    }

    public List<StyleImportDTO> readExcelData(String excelFilePath){
        //创建监听实例
        IndexOrNameDataListener listener = new IndexOrNameDataListener();
        // 这里默认读取第一个sheet
        EasyExcel.read(excelFilePath, StyleImportDTO.class,listener).sheet().doRead();
        //将数据封装到数据列表
        return listener.getDataList();
    }
}
